package com.vhall.component.service.goods.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.dao.goods.LiveGoodsStatsDetailMapper;
import com.vhall.component.dao.goods.LiveGoodsStatsMapper;
import com.vhall.component.entity.goods.LiveGoodsEntity;
import com.vhall.component.entity.goods.LiveGoodsStatsDetailEntity;
import com.vhall.component.entity.goods.LiveGoodsStatsEntity;
import com.vhall.component.entity.goods.goods.GoodsApiSendMessageReqVO;
import com.vhall.component.entity.room.entity.RoomGoodsEntity;
import com.vhall.component.plugin.common.utils.RedisLocker;
import com.vhall.component.service.goods.LiveGoodsStatsService;
import com.vhall.component.service.goods.common.GoodsConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author yuanzh
 */
@Slf4j
@Service
public class LiveGoodsStatsServiceImpl implements LiveGoodsStatsService {

    @Autowired
    private LiveGoodsStatsMapper liveGoodsStatsMapper;

    @Autowired
    private LiveGoodsStatsDetailMapper liveGoodsStatsDetailMapper;

    @Override
    public boolean handleUpdateGoodsStats(GoodsApiSendMessageReqVO reqVO, RoomGoodsEntity bindInfo, LocalDateTime currentTime) {
        Integer bgId = bindInfo.getId();
        Integer ilId = bindInfo.getIlId();
        LambdaQueryWrapper<LiveGoodsStatsEntity> queryStats = Wrappers.lambdaQuery();
        queryStats.eq(LiveGoodsStatsEntity::getBgId, bgId);
        queryStats.eq(LiveGoodsStatsEntity::getIlId, ilId);
        String createDate = DateUtil.format(currentTime, DatePattern.NORM_DATE_PATTERN);
        queryStats.eq(LiveGoodsStatsEntity::getCreateDate, createDate);
        LiveGoodsStatsEntity goodsStatsInfo = liveGoodsStatsMapper.selectOne(queryStats);
        if (Objects.isNull(goodsStatsInfo)) {
            StringBuilder lockKey = new StringBuilder();
            lockKey.append(GoodsConstant.GOODS_STATS_LOCK_KEY).append("_").append(bgId).append("_").append(ilId).append("_")
                    .append(createDate);
            String lockValue = "1";
            // 加锁
            if (!RedisLocker.tryLock(lockKey.toString(), lockValue, 10 * 1000L)) {
                try {
                    Thread.sleep(50L);
                } catch (InterruptedException e) {
                    log.error("Interrupted!", e);
                    Thread.currentThread().interrupt();
                }
                return handleUpdateGoodsStats(reqVO, bindInfo, currentTime);
            }
            try {
                // 插入操作。
                LiveGoodsStatsEntity insertEntity = new LiveGoodsStatsEntity();
                insertEntity.setBgId(bgId);
                insertEntity.setIlId(ilId);
                insertEntity.setPushScreenNum(1);
                insertEntity.setDuration(reqVO.getScreenSecond());
                insertEntity.setCreateDate(createDate);
                insertEntity.setCreatedAt(LocalDateTime.now());
                liveGoodsStatsMapper.insert(insertEntity);
                return true;
            } finally {
                RedisLocker.unlock(lockKey.toString(), lockValue);
            }
        }
        // 推屏次数+1，推屏时长+reqVO.getScreenSecond()
        liveGoodsStatsMapper.incrPushScreenAndDuration(goodsStatsInfo.getId(), reqVO.getScreenSecond(), LocalDateTime.now());
        return true;
    }

    @Override
    public boolean handleIncrGoodsStatsPvUv(int bgId, int ilId, Integer accountId, LocalDateTime currentTime) {
        LambdaQueryWrapper<LiveGoodsStatsEntity> queryStats = Wrappers.lambdaQuery();
        queryStats.eq(LiveGoodsStatsEntity::getBgId, bgId);
        queryStats.eq(LiveGoodsStatsEntity::getIlId, ilId);
        String createDate = DateUtil.format(currentTime, DatePattern.NORM_DATE_PATTERN);
        queryStats.eq(LiveGoodsStatsEntity::getCreateDate, createDate);
        LiveGoodsStatsEntity goodsStatsInfo = liveGoodsStatsMapper.selectOne(queryStats);
        if (Objects.isNull(goodsStatsInfo)) {
            StringBuilder lockKey = new StringBuilder();
            lockKey.append(GoodsConstant.GOODS_STATS_LOCK_KEY).append("_").append(bgId).append("_").append(ilId).append("_")
                    .append(createDate);
            String lockValue = "1";
            // 加锁
            if (!RedisLocker.tryLock(lockKey.toString(), lockValue, 10 * 1000L)) {
                try {
                    Thread.sleep(50L);
                } catch (InterruptedException e) {
                    log.error("Interrupted!", e);
                    Thread.currentThread().interrupt();
                }
                return handleIncrGoodsStatsPvUv(bgId, ilId, accountId, currentTime);
            }
            try {
                // 插入操作。
                LiveGoodsStatsEntity insertEntity = new LiveGoodsStatsEntity();
                insertEntity.setBgId(bgId);
                insertEntity.setIlId(ilId);
                insertEntity.setPvNum(1);
                insertEntity.setUvNum(1);
                insertEntity.setCreateDate(createDate);
                insertEntity.setCreatedAt(LocalDateTime.now());
                liveGoodsStatsMapper.insert(insertEntity);
                return true;
            } finally {
                RedisLocker.unlock(lockKey.toString(), lockValue);
            }
        }
        // 点击次数&点击人数自增1
        // 判断当前用户是否已经计算过。通过查询detail表判断。
        LambdaQueryWrapper<LiveGoodsStatsDetailEntity> queryStatsDetail = Wrappers.lambdaQuery();
        queryStatsDetail.eq(LiveGoodsStatsDetailEntity::getUserId, accountId);
        queryStatsDetail.eq(LiveGoodsStatsDetailEntity::getBgId, bgId);
        queryStatsDetail.eq(LiveGoodsStatsDetailEntity::getIlId, ilId);
        queryStatsDetail.eq(LiveGoodsStatsDetailEntity::getType, GoodsConstant.OPERATE_TYPE_CLICK);
        // 按天控制uv，一天累计一次
        LocalDateTime startTime = DateUtil.parseLocalDateTime(createDate, DatePattern.NORM_DATE_PATTERN);
        queryStatsDetail.ge(LiveGoodsStatsDetailEntity::getCreatedAt, startTime);
        queryStatsDetail.lt(LiveGoodsStatsDetailEntity::getCreatedAt, startTime.plusDays(1));
        Integer count = liveGoodsStatsDetailMapper.selectCount(queryStatsDetail);
        if (count > 1) {
            liveGoodsStatsMapper.incrPv(goodsStatsInfo.getId(), LocalDateTime.now());
        } else {
            liveGoodsStatsMapper.incrPvAndUv(goodsStatsInfo.getId(), LocalDateTime.now());
        }
        return true;
    }
}
